#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <semaphore.h>
#include <signal.h>
#include <assert.h>

#define DEFAULT_ADD_NUM 5
#define DEFAULT_REMOVE_NUM 2
#define MANAGER_CHECK_INTERVAL 3

struct Job {
    void (*task)(void *arg);
    void *arg;
    struct Job *next;
};

struct thread_pool {
    int min_thread_num;
    int max_thread_num;
    int alive_thread_num;
    int busy_thread_num;
    int wait_exit_thread_num;

    int queue_max_size;
    int queue_cur_size;

    pthread_t *ids;
    pthread_t manager_id;
    pthread_mutex_t mutex;
    pthread_mutex_t busy_mutex;
    pthread_cond_t empty_queue;
    pthread_cond_t not_empty_queue;
    pthread_cond_t not_full_queue;

    struct Job *head;
    struct Job *tail;

    int shutdown;       // 线程池关闭标志
    int queue_closed;   // 任务队列关闭标志
};

struct thread_pool *pool;

// 线程是否存活的检查函数
static int is_thread_alive(pthread_t id) {
    return pthread_kill(id, 0) == ESRCH ? 0 : 1;
}

// 添加任务到线程池
void thread_add_job(struct thread_pool *pool, void (*task)(void *), void *arg) {
    assert(pool != NULL);

    pthread_mutex_lock(&(pool->mutex));

    // 检查线程池和队列状态
    if (pool->shutdown || pool->queue_closed) {
        pthread_mutex_unlock(&(pool->mutex));
        fprintf(stderr, "Cannot add job: pool is shutting down\n");
        return;
    }

    // 等待队列有空闲位置
    while (pool->queue_cur_size >= pool->queue_max_size && !pool->shutdown) {
        pthread_cond_wait(&(pool->not_full_queue), &(pool->mutex));
    }

    // 再次检查状态
    if (pool->shutdown || pool->queue_closed) {
        pthread_mutex_unlock(&(pool->mutex));
        return;
    }

    // 创建新任务
    struct Job *new_job = (struct Job *)malloc(sizeof(struct Job));
    if (!new_job) {
        pthread_mutex_unlock(&(pool->mutex));
        perror("Failed to allocate job");
        return;
    }
    
    new_job->task = task;
    new_job->arg = arg;
    new_job->next = NULL;

    // 添加到队列
    if (pool->head == NULL) {
        pool->head = pool->tail = new_job;
    } else {
        pool->tail->next = new_job;
        pool->tail = new_job;
    }

    pool->queue_cur_size++;
    
    // 通知有任务可用
    pthread_cond_signal(&(pool->not_empty_queue));
    pthread_mutex_unlock(&(pool->mutex));
}

// 工作线程函数
void *thread_function(void *arg) {
    struct thread_pool *pool = (struct thread_pool *)arg;
    struct Job *job = NULL;

    while (1) {
        pthread_mutex_lock(&(pool->mutex));
        
        // 等待任务或退出信号
        while (pool->queue_cur_size == 0 && !pool->shutdown) {
            // 检查是否需要减少线程
            if (pool->wait_exit_thread_num > 0) {
                pool->wait_exit_thread_num--;
                pool->alive_thread_num--;
                
                // 从线程ID数组中移除当前线程
                for (int i = 0; i < pool->max_thread_num; i++) {
                    if (pthread_equal(pool->ids[i], pthread_self())) {
                        pool->ids[i] = 0;
                        break;
                    }
                }
                
                pthread_mutex_unlock(&(pool->mutex));
                printf("Thread %lu exiting due to reduce request\n", pthread_self());
                pthread_exit(NULL);
            }
            
            pthread_cond_wait(&(pool->not_empty_queue), &(pool->mutex));
        }

        // 检查线程池是否关闭
        if (pool->shutdown) {
            pthread_mutex_unlock(&(pool->mutex));
            printf("Thread %lu exiting due to pool shutdown\n", pthread_self());
            break;
        }

        // 获取任务
        job = pool->head;
        if (job == NULL) {
            pthread_mutex_unlock(&(pool->mutex));
            continue;
        }

        // 更新队列
        pool->head = job->next;
        pool->queue_cur_size--;
        
        if (pool->queue_cur_size == 0) {
            pool->tail = NULL;
            pthread_cond_signal(&(pool->empty_queue));
        }
        
        pthread_cond_signal(&(pool->not_full_queue));
        pthread_mutex_unlock(&(pool->mutex));

        // 执行任务
        pthread_mutex_lock(&(pool->busy_mutex));
        pool->busy_thread_num++;
        pthread_mutex_unlock(&(pool->busy_mutex));
        
        job->task(job->arg);
        
        pthread_mutex_lock(&(pool->busy_mutex));
        pool->busy_thread_num--;
        pthread_mutex_unlock(&(pool->busy_mutex));

        // 释放任务资源
        free(job);
        job = NULL;
    }

    // 线程退出前更新计数
    pthread_mutex_lock(&(pool->mutex));
    pool->alive_thread_num--;
    pthread_mutex_unlock(&(pool->mutex));
    
    return NULL;
}

// 管理者线程函数
void *manager_thread_function(void *arg) {
    struct thread_pool *pool = (struct thread_pool *)arg;
    int busy_num, alive_num;
    
    while (!pool->shutdown) {
        sleep(MANAGER_CHECK_INTERVAL);
        
        pthread_mutex_lock(&(pool->mutex));
        alive_num = pool->alive_thread_num;
        pthread_mutex_unlock(&(pool->mutex));
        
        pthread_mutex_lock(&(pool->busy_mutex));
        busy_num = pool->busy_thread_num;
        pthread_mutex_unlock(&(pool->busy_mutex));
        
        // 任务多，线程少 - 增加线程
        pthread_mutex_lock(&(pool->mutex));
        if ((pool->queue_cur_size > pool->queue_max_size / 2) && 
            (alive_num < pool->max_thread_num)) {
            
            int add_num = DEFAULT_ADD_NUM;
            if (alive_num + add_num > pool->max_thread_num) {
                add_num = pool->max_thread_num - alive_num;
            }
            
            for (int i = 0; i < pool->max_thread_num && add_num > 0; i++) {
                if (pool->ids[i] == 0 || !is_thread_alive(pool->ids[i])) {
                    if (pthread_create(&(pool->ids[i]), NULL, thread_function, pool) == 0) {
                        pool->alive_thread_num++;
                        add_num--;
                    }
                }
            }
        }
        
        // 线程多，任务少 - 减少线程
        if ((busy_num * 4 < alive_num) && 
            (alive_num > pool->min_thread_num)) {
            
            int remove_num = DEFAULT_REMOVE_NUM;
            if (alive_num - remove_num < pool->min_thread_num) {
                remove_num = alive_num - pool->min_thread_num;
            }
            
            pool->wait_exit_thread_num = remove_num;
            for (int i = 0; i < remove_num; i++) {
                pthread_cond_signal(&(pool->not_empty_queue));
            }
        }
        pthread_mutex_unlock(&(pool->mutex));
    }
    
    return NULL;
}

// 创建线程池
struct thread_pool *thread_pool_create(int min_num, int max_num, int queue_max_size) {
    if (min_num <= 0 || max_num <= 0 || min_num > max_num || queue_max_size <= 0) {
        fprintf(stderr, "Invalid thread pool parameters\n");
        return NULL;
    }

    struct thread_pool *pool = (struct thread_pool *)calloc(1, sizeof(struct thread_pool));
    if (!pool) {
        perror("Failed to allocate thread pool");
        return NULL;
    }

    pool->min_thread_num = min_num;
    pool->max_thread_num = max_num;
    pool->alive_thread_num = min_num;
    pool->busy_thread_num = 0;
    pool->wait_exit_thread_num = 0;

    pool->queue_max_size = queue_max_size;
    pool->queue_cur_size = 0;

    pool->head = pool->tail = NULL;
    pool->shutdown = 0;
    pool->queue_closed = 0;

    // 初始化锁和条件变量
    if (pthread_mutex_init(&(pool->mutex), NULL) != 0 ||
        pthread_mutex_init(&(pool->busy_mutex), NULL) != 0 ||
        pthread_cond_init(&(pool->not_empty_queue), NULL) != 0 ||
        pthread_cond_init(&(pool->not_full_queue), NULL) != 0 ||
        pthread_cond_init(&(pool->empty_queue), NULL) != 0) {
        perror("Failed to initialize mutex or condition");
        free(pool);
        return NULL;
    }

    // 分配线程ID数组
    pool->ids = (pthread_t *)calloc(max_num, sizeof(pthread_t));
    if (!pool->ids) {
        perror("Failed to allocate thread IDs");
        pthread_mutex_destroy(&(pool->mutex));
        pthread_mutex_destroy(&(pool->busy_mutex));
        pthread_cond_destroy(&(pool->not_empty_queue));
        pthread_cond_destroy(&(pool->not_full_queue));
        pthread_cond_destroy(&(pool->empty_queue));
        free(pool);
        return NULL;
    }

    // 创建工作线程
    for (int i = 0; i < min_num; i++) {
        if (pthread_create(&(pool->ids[i]), NULL, thread_function, pool) != 0) {
            perror("Failed to create worker thread");
            // 清理已创建的线程
            for (int j = 0; j < i; j++) {
                pthread_cancel(pool->ids[j]);
            }
            free(pool->ids);
            pthread_mutex_destroy(&(pool->mutex));
            pthread_mutex_destroy(&(pool->busy_mutex));
            pthread_cond_destroy(&(pool->not_empty_queue));
            pthread_cond_destroy(&(pool->not_full_queue));
            pthread_cond_destroy(&(pool->empty_queue));
            free(pool);
            return NULL;
        }
    }

    // 创建管理者线程
    if (pthread_create(&(pool->manager_id), NULL, manager_thread_function, pool) != 0) {
        perror("Failed to create manager thread");
        for (int i = 0; i < min_num; i++) {
            pthread_cancel(pool->ids[i]);
        }
        free(pool->ids);
        pthread_mutex_destroy(&(pool->mutex));
        pthread_mutex_destroy(&(pool->busy_mutex));
        pthread_cond_destroy(&(pool->not_empty_queue));
        pthread_cond_destroy(&(pool->not_full_queue));
        pthread_cond_destroy(&(pool->empty_queue));
        free(pool);
        return NULL;
    }

    return pool;
}

// 销毁线程池
void thread_pool_destroy(struct thread_pool *pool) {
    if (!pool) return;

    pthread_mutex_lock(&(pool->mutex));
    pool->queue_closed = 1;
    
    // 等待所有任务完成
    while (pool->queue_cur_size > 0) {
        pthread_cond_wait(&(pool->empty_queue), &(pool->mutex));
    }
    
    pool->shutdown = 1;
    pthread_cond_broadcast(&(pool->not_empty_queue));
    pthread_cond_broadcast(&(pool->not_full_queue));
    pthread_mutex_unlock(&(pool->mutex));

    // 等待所有线程退出
    pthread_join(pool->manager_id, NULL);
    
    for (int i = 0; i < pool->max_thread_num; i++) {
        if (pool->ids[i] != 0 && is_thread_alive(pool->ids[i])) {
            pthread_join(pool->ids[i], NULL);
        }
    }

    // 清理资源
    while (pool->head != NULL) {
        struct Job *tmp = pool->head;
        pool->head = pool->head->next;
        free(tmp);
    }

    free(pool->ids);
    pthread_mutex_destroy(&(pool->mutex));
    pthread_mutex_destroy(&(pool->busy_mutex));
    pthread_cond_destroy(&(pool->not_empty_queue));
    pthread_cond_destroy(&(pool->not_full_queue));
    pthread_cond_destroy(&(pool->empty_queue));
    free(pool);
}

// 示例任务函数
void task(void *arg) {
    int num = (int)(long)arg;
    printf("Task %d started by thread %lu\n", num, pthread_self());
    sleep(1); // 模拟工作负载
    printf("Task %d completed by thread %lu\n", num, pthread_self());
}

// 信号处理函数
void thread_exit(int sig) {
    if (sig == SIGINT) {
        printf("\nShutting down thread pool...\n");
        thread_pool_destroy(pool);
        exit(0);
    }
}

int main(int argc, char **argv) {
    signal(SIGINT, thread_exit);

    // 创建线程池: 最小5线程，最大30线程，队列大小10000
    pool = thread_pool_create(5, 30, 10000);
    if (!pool) {
        fprintf(stderr, "Failed to create thread pool\n");
        return 1;
    }

    // 添加10000个任务
    for (int i = 0; i < 10000; i++) {
        thread_add_job(pool, task, (void *)(long)i);
    }

    // 主线程等待
    pause();
    return 0;
}